package com.powergisol.gis.listener;

import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.powergisol.gis.entity.TabCoordinateSystem;
import com.powergisol.gis.entity.TabZkShuiwei;
import com.powergisol.gis.entity.TabZkTuceng;
import com.powergisol.gis.entity.TabZuankong;
import com.powergisol.gis.service.SaveDataService;
import com.powergisol.gis.util.XyChangeUtil;
import com.powergisol.gis.vo.CnyZkExcelStandardVo;
import com.powergisol.gis.vo.ExcelInFailedDataVo;
import com.powergisol.gis.vo.TaskResultVo;
import org.apache.commons.lang.StringUtils;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;

import java.math.BigDecimal;
import java.security.Principal;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

/**
 * Created By marc
 * Date: 2020/9/3  16:07
 * Description:
 */
public class CnyExcelModelListener extends AnalysisEventListener {

//    private static  final int READ_NUM = 3;

    private final static Pattern NUMBER_PATTERN = Pattern.compile("([+\\-]?[0-9]+[.]?[\\d]*)");


    //组装数据存放
    CnyZkExcelStandardVo vo;

    TabCoordinateSystem system;

    SaveDataService saveDataService;

    CacheManager cacheManager;

    Integer settingId;


    String excelName;

    //编码所在列数
    private Integer codeColumn;
    //字段值所在列数
    private Integer valueColumn;


    public CnyExcelModelListener() {
    }

    public CnyExcelModelListener(CnyZkExcelStandardVo vo, SaveDataService saveDataService, Integer settingId,
                                 CacheManager cacheManager, TabCoordinateSystem system, String excelName) {
        this.vo = vo;
        this.saveDataService = saveDataService;
        this.settingId = settingId;
        this.cacheManager = cacheManager;
        this.system = system;
        this.excelName =  excelName;
    }
    @Override
    public void invoke(Object o, AnalysisContext analysisContext) {
        ArrayList data = (ArrayList) o;
        try{
            if(data.isEmpty()){
                return;
            }
            int j = 0;
            int num = data.size();
            for(int i=0; i<num; i++){
                if(j>0){
                    return;
                }
                String str = String.valueOf(data.get(i));
                if(StringUtils.isBlank(str)) continue;
                //如果列数存在
                if(null == valueColumn && str.equals("字段值")){
                    valueColumn = i;
                }
                switch (str){
                    //分类编码
                    case "Hcdm01":
                        vo.setHcdm01(valueColumn >= num?null:data.get(valueColumn) == null ? null : data.get(valueColumn).toString());
                        j = j+1;
                        break;
                    //项目勘察钻孔编号
                    case "Hcdm02":
                        vo.setHcdm02(valueColumn >= num?null:data.get(valueColumn) == null ? null : data.get(valueColumn).toString());
                        j = j+1;
                        break;
                    //勘探点类型
                    case "Hcdm03":
                        vo.setZKLX(valueColumn >= num?null:data.get(valueColumn) == null ? null : data.get(valueColumn).toString());
                        j = j+1;
                        break;
                    //勘探点编号
                    case "Hcdm04":
                        vo.setZKBH(valueColumn >= num?null:data.get(valueColumn) == null ? null : data.get(valueColumn).toString());
                        j = j+1;
                        break;
                    //序号
                    case "Hcdm05":
                        vo.setHcdm05(valueColumn >= num?null:data.get(valueColumn) == null ? null : data.get(valueColumn).toString());
                        j = j+1;
                        break;
                    //变更提示:有变更1、无变更0
                    case "KC00":
                        j = j+1;
                        break;
                    //阶段:设计1、合约2、实施3
                    case "KC01":
                        j = j+1;
                        break;
                    //交付日期
                    case "KC02":
                        j = j+1;
                        break;
                    //数据创建人
                    case "KC03":
                        j = j+1;
                        break;
                    //数据创建人
                    case "KC04":
                        j = j+1;
                        break;
                    //坐标Xl
                    case "KC21":
                        vo.setZKX(valueColumn >= num?null:data.get(valueColumn) == null ? null : data.get(valueColumn).toString());
                        j = j+1;
                        break;
                    //坐标Yw
                    case "KC22":
                        vo.setZKY(valueColumn >= num?null:data.get(valueColumn) == null ? null : data.get(valueColumn).toString());
                        j = j+1;
                        break;
                    //地面高程Zh
                    case "KC23":
                        vo.setZKBG(valueColumn >= num?null:data.get(valueColumn) == null ? null : data.get(valueColumn).toString());
                        j = j+1;
                        break;
                    //钻孔直径
                    case "KC24":
                        vo.setZKZJ(valueColumn >= num?null:data.get(valueColumn) == null ? null : data.get(valueColumn).toString());
                        j = j+1;
                        break;
                    //钻探深度
                    case "KC25":
                        vo.setZKSD(valueColumn >= num?null:data.get(valueColumn) == null ? null : data.get(valueColumn).toString());
                        j = j+1;
                        break;
                    //钻孔地下水层数
                    case "KC27":
                        vo.setSWNUM(valueColumn >= num?null:data.get(valueColumn) == null ? null : data.get(valueColumn).toString());
                        j = j+1;
                        break;
                    //地下水历年最高水位
                    case "KC28":
                       // vo.setZKDXSW(i+2 > num?null:data.get(i+2) == null ? null : data.get(i+2).toString());
                        j = j+1;
                        break;
                    //地下水近3-5年最高水位
                    case "KC29":
                        vo.setZKPZTSDXS(valueColumn >= num?null:data.get(valueColumn) == null ? null : data.get(valueColumn).toString());
                        j = j+1;
                        break;
                    //地下水位：埋深
                    case "KC56":
                        vo.setSWSD(valueColumn >= num?null:data.get(valueColumn) == null ? null : data.get(valueColumn).toString());
                        j = j+1;
                        break;
                    //高程
                    case "KC57":
                        vo.setSWDXSW(valueColumn >= num?null:data.get(valueColumn) == null ? null : data.get(valueColumn).toString());
                        j = j+1;
                        break;
                    //标贯
                    case "KC58":
                        j = j+1;
                        break;
                    //地层数
                    case "KC26":
                        vo.setTCNUM(valueColumn >= num?null:data.get(valueColumn) == null ? null : data.get(valueColumn).toString());
                        j = j+1;
                        break;
                    //时代成因
                    case "TC（1，i）":
                        if(valueColumn <= num){
                            List<String> TCSDCY = new ArrayList<String> ();
                            for (int numj = valueColumn; numj < data.size(); numj++) {
                                TCSDCY.add(null == data.get(numj)? null : data.get(numj).toString());
                            }
                            vo.setTCSDCY(TCSDCY);
                        }
                        j = j+1;
                        break;
                    //地层（岩土）编号
                    case "TC（2，i）":
                        if(valueColumn <= num){
                            List<String> TCBH = new ArrayList<String> ();
                            for (int numj = valueColumn; numj < data.size(); numj++) {
                                TCBH.add(null == data.get(numj)? null : data.get(numj).toString());
                            }
                            vo.setTCBH(TCBH);
                        }
                        j = j+1;
                        break;
                    //岩土名称
                    case "TC（3，i）":
                        if(valueColumn <= num){
                            List<String> TCMC = new ArrayList<String> ();
                            for (int numj = valueColumn; numj < data.size(); numj++) {
                                TCMC.add(null == data.get(numj)? null : data.get(numj).toString());
                            }
                            vo.setTCMC(TCMC);
                        }
                        j = j+1;
                        break;
                    //土层深度
                    case "TC（4，i）":
                        if(valueColumn <= num){
                            List<String> TCCDSD = new ArrayList<String> ();
                            for (int numj = valueColumn; numj < data.size(); numj++) {
                                TCCDSD.add(null == data.get(numj)? null : data.get(numj).toString());
                            }
                            vo.setTCCDSD(TCCDSD);
                        }
                        j = j+1;
                        break;
                    //土层描述
                    case "TC（5，i）":
                        if(valueColumn <= num){
                            List<String> TCMS = new ArrayList<String> ();
                            for (int numj = valueColumn; numj < data.size(); numj++) {
                                TCMS.add(null == data.get(numj)? null : data.get(numj).toString());
                            }
                            vo.setTCMS(TCMS);
                        }
                        j = j+1;
                        break;
                    /**
                     * 土的物理性质
                     */
                        //含水率ω
                    case "TC（6，i）":
                        j = j+1;
                        break;
                    //土粒比重Gs
                    case "TC（7，i）":
                        j = j+1;
                        break;
                    //湿密度ρ
                    case "TC（8，i）":
                        j = j+1;
                        break;
                    //干密度ρ1
                    case "TC（9，i）":
                        j = j+1;
                        break;
                    //饱和度Sr
                    case "TC（10，i）":
                        j = j+1;
                        break;
                    //孔隙比e
                    case "TC（11，i）":
                        j = j+1;
                        break;
                    /**
                     * 界限含水率
                     */
                        //10mm液限ωL
                    case "TC（1READ_NUM，i）":
                        j = j+1;
                        break;
                    //塑限ωp
                    case "TC（13，i）":
                        j = j+1;
                        break;
                    //塑性指数Ip
                    case "TC（14，i）":
                        j = j+1;
                        break;
                    //液性指数IL
                    case "TC（15，i）":
                        j = j+1;
                        break;
                    //压缩系数aV1-2
                    case "TC（16，i）":
                        j = j+1;
                        break;
                    //压缩模量Es1-2
                    case "TC（17，i）":
                        j = j+1;
                        break;
                    //内聚力c
                    case "TC（18，i）":
                        j = j+1;
                        break;
                    //摩擦角φ
                    case "TC（19，i）":
                        j = j+1;
                        break;
                    //有机质含量
                    case "TC（20，i）":
                        j = j+1;
                        break;
                    //钻探开始日期
                    case "KC401":
                        vo.setZKKSRQ(valueColumn >= num?null:data.get(valueColumn) == null ? null : data.get(valueColumn).toString());
                        j = j+1;
                        break;
                    //钻探终止日期
                    case "KC402":
                        vo.setZKZZRQ(valueColumn >= num?null:data.get(valueColumn) == null ? null : data.get(valueColumn).toString());
                        j = j+1;
                        break;
                    /**
                     * 标贯
                     */
                        //试验段深度
                    case "BG（1，i）":
                        j = j+1;
                        break;
                    //标贯击数N（击/30cm）
                    case "BG（2，i）":
                        j = j+1;
                        break;
                    //探杆长度
                    case "BG（3，i）":
                        j = j+1;
                        break;
                    //标贯修正击数N（击/30cm）
                    case "BG（4，i）":
                        j = j+1;
                        break;
                   default :
                       break;
                }
            }

        }catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        saveData(vo);
    }
    private void saveData(CnyZkExcelStandardVo vo){
        try{
            List<ExcelInFailedDataVo> listFailed = new ArrayList<>();//失败数据
            BigDecimal lat = BigDecimal.ZERO;
            BigDecimal lon = BigDecimal.ZERO;
            BigDecimal x = BigDecimal.ZERO;
            BigDecimal y = BigDecimal.ZERO;
            if(!NUMBER_PATTERN.matcher(vo.getZKX()).matches()){
                dealFail("坐标Xl需为数字");
                return;
            }
            if(!NUMBER_PATTERN.matcher(vo.getZKY()).matches()){
                dealFail("坐标Yw需为数字");
                return;
            }
            if(1 == vo.getIsChange()){
                lat = XyChangeUtil.change(Double.valueOf(vo.getZKX()), Double.valueOf(vo.getZKY()),system.getCoorChangeLat());
                lon = XyChangeUtil.change(Double.valueOf(vo.getZKX()), Double.valueOf(vo.getZKY()),system.getCoorChangeLon());
            }else{
                lat = new BigDecimal(vo.getZKY());//纬度
                lon = new BigDecimal(vo.getZKX());//经度
            }            //经度-180-180 纬度-90-90
            if (lon.compareTo(new BigDecimal("180")) > 0 || lon.compareTo(new BigDecimal("-180")) < 0 ||
                    lat.compareTo(new BigDecimal("90")) > 0 || lat.compareTo(new BigDecimal("-90")) < 0) {
                dealFail("坐标Xl或坐标Yw不在范围内");
                return;
            }
            x = new BigDecimal(vo.getZKX());
            y = new BigDecimal(vo.getZKY());

            Integer tcNum = Integer.valueOf(vo.getTCNUM());
            List<TabZuankong> listZk = new ArrayList<>();//存放钻孔数据
            List<TabZkTuceng> listTc = new ArrayList<>();//存放土层数据
            List<TabZkShuiwei> listSw = new ArrayList<>();//存放水位数据

            List<String> TCBH = vo.getTCBH();
            List<String> TCCDSD = vo.getTCCDSD();
            List<String> TCMC = vo.getTCMC();
            List<String> TCSDCY = vo.getTCSDCY();
            List<String> TCMS = vo.getTCMS();
            BigDecimal tccdsd = BigDecimal.ZERO;
            BigDecimal tccdsdPer = BigDecimal.ZERO;
            if(TCCDSD.size()>0) {
                for (int i = 0; i < tcNum; i++) {
                    if (1 == 0) {
                        tccdsd = new BigDecimal(TCCDSD.get(i));
                        tccdsdPer = new BigDecimal(TCCDSD.get(i));
                    } else {
                        tccdsd = new BigDecimal(TCCDSD.get(i)).subtract(tccdsdPer);
                        tccdsdPer = new BigDecimal(TCCDSD.get(i));
                    }
                    TabZuankong zk = new TabZuankong();
                    TabZkTuceng tc = new TabZkTuceng();
                    zk.setZKBH(vo.getZKBH());
                    zk.setZKBG(new BigDecimal(vo.getZKBG()));
                    zk.setZKLX(vo.getZKLX());
                    zk.setGCMC(vo.getFileName());
                    if (null != vo.getZKSD()) {
                        zk.setZKSD(new BigDecimal(vo.getZKSD()));
                    }
                    if (null != vo.getZKZJ()) {
                        zk.setZKZJ(new BigDecimal(vo.getZKZJ()));
                    }
                    if (null != vo.getZKDXSW()) {
                        zk.setZKDXSW(new BigDecimal(vo.getZKDXSW()));
                    }
                    if (null != vo.getZKPZTSDXS()) {
                        zk.setZKPZTSDXS(new BigDecimal(vo.getZKPZTSDXS()));
                    }
                    zk.setZKX(lon);
                    zk.setZKY(lat);
//                    String coor = "POINT({} {})";
//                    coor = StrUtil.format(coor, lon, lat);
//                    zk.setCoor(coor);
                    zk.setZKOX(x);
                    zk.setZKOY(y);
                    zk.setZKKSRQ(vo.getZKKSRQ());
                    zk.setZKZZRQ(vo.getZKZZRQ());
                    zk.setDataIndex(i + 1);
                    zk.setSettingId(settingId);
                    zk.setHcdm01(vo.getHcdm01());
                    zk.setHcdm02(vo.getHcdm02());
                    zk.setHcdm05(vo.getHcdm05());
                    listZk.add(zk);
                    tc.setZKBH(vo.getZKBH());
                    tc.setTCCDSD(new BigDecimal(TCCDSD.get(i)));
                    zk.setTCCDSD(new BigDecimal(TCCDSD.get(i)));
                    tc.setTCHD(tccdsd);
                    zk.setTCHD(tccdsd);
                    tc.setTCXH(i + 1);
                    if (null != TCBH && TCBH.size() > 0 && i < TCBH.size()) {
                        String tcbh = TCBH.get(i);
                        tc.setTCBH(tcbh);
                        if (null != tcbh && !("").equals(tcbh)) {
                            String[] xh = tcbh.split("-");
                            if (xh.length > 0 && null != xh[0] && !("").equals(xh[0]) && isNumber(xh[0])) {
                                tc.setTCZCBH(Integer.valueOf(xh[0]));
                            }
                            if (xh.length > 1 && null != xh[1] && !("").equals(xh[1]) && isNumber(xh[1])) {
                                tc.setTCYCBH(Integer.valueOf(xh[1]));
                            }
                            if (xh.length > 2 && null != xh[2] && !("").equals(xh[2]) && isNumber(xh[2])) {
                                tc.setTCCYCBH(Integer.valueOf(xh[2]));
                            }
                        }
                    }

                    tc.setDataIndex(i + 1);
                    tc.setSettingId(settingId);
                    if (null != TCMC && TCMC.size() > 0 && i < TCMC.size()) {
                        tc.setTCMC(TCMC.get(i));
                        zk.setTCMC(TCMC.get(i));
                    }

                    if (null != TCSDCY && TCSDCY.size() > 0 && i < TCSDCY.size()) {
                        tc.setTCSDCY(TCSDCY.get(i));
                    }

                    if (null != TCMS && TCMS.size() > 0 && i < TCMS.size()) {
                        tc.setTCMS(TCMS.get(i));
                    }

                    //直剪粘聚力
//                if(i<vo.getTCNJL().size()){
//                    BigDecimal zkzjlx = null == vo.getTCNJL().get(i)?null:new BigDecimal(vo.getTCNJL().get(i));
//                    tc.setTCNJL(zkzjlx);
//                }
//
//                //直剪内摩擦角
//                if(i<vo.getTCNMCJ().size()){
//                    BigDecimal tcnmcj = null == vo.getTCNMCJ().get(i)?null:new BigDecimal(vo.getTCNMCJ().get(i));
//                    tc.setTCNMCJ(tcnmcj);
//                }

                    listTc.add(tc);
                }
            }

            TabZkShuiwei sw = new TabZkShuiwei();
            sw.setDataIndex(1);
            sw.setZKBH(vo.getZKBH());
            sw.setSWSD(null == vo.getSWSD()?null:new BigDecimal(vo.getSWSD()));
            sw.setSWDXSW(null == vo.getSWDXSW()? null : new BigDecimal(vo.getSWDXSW()));
            sw.setSettingId(settingId);
            listSw.add(sw);

            //存库
            if(listZk.size()>0){
                saveDataService.saveBatch(listZk);
            }
            if(listTc.size()>0){
                saveDataService.saveBatch(listTc);
            }
            if(listSw.size()>0){
                saveDataService.saveBatch(listSw);
            }
        }catch (Exception e){
            e.printStackTrace();
            dealFail("解析失败");
        }

    }

    private void dealFail(String msg){
        List<ExcelInFailedDataVo> listFailed = new ArrayList<>();
        ExcelInFailedDataVo failedDataVo = new ExcelInFailedDataVo();
        failedDataVo.setReason(msg);
        failedDataVo.setRowIndex(excelName);
        listFailed.add(failedDataVo);
        Cache cache = cacheManager.getCache("cache-data");
        TaskResultVo resultVo = new TaskResultVo();
        resultVo.setListFailed(listFailed);
        cache.put(vo.getUuid() +"sb",resultVo);
    }

    private boolean isNumber(String value) {
        String matchStr = "^\\d+$";
        return value.matches(matchStr);
    }

}
